package com.ibeeking.found.id.rest.service.impl;

import com.ibeeking.found.common.constants.IdRedisConstant;
import com.ibeeking.found.id.rest.service.IGenerateIdService;
import com.ibeeking.nematos.redis.utils.RedisUtils;
import com.ibeeking.nematos.utils.id.IdGenerator;
import com.ibeeking.nematos.utils.id.Sequence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName GenerateIdServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2020-07-16 10:47
 **/
@Service
@RefreshScope
public class GenerateIdServiceImpl implements IGenerateIdService {
    private static final Logger log = LoggerFactory.getLogger(GenerateIdServiceImpl.class);

    @Value("${generateId.lowCount:1000}")
    private int lowCount;

    @Value("${generateId.count:10000}")
    private int count;

    @Resource
    private RedisUtils redisUtils;
    @Resource
    private Sequence sequence;

    @Override
    public int ckeckGenerateId() {
        String key = String.valueOf(IdGenerator.getId());
        int havaSize = 0;
        try {
            if (redisUtils.tryLock(key, 10, 15)) {
                havaSize = redisUtils.lSize(IdRedisConstant.SNOWFLAKE_ID).intValue();
            }
        } finally {
            redisUtils.unlock(key);
        }
        if (lowCount >= havaSize) {
            this.compensateGenerateId();
        }
        return havaSize;
    }

    @Override
    public int compensateGenerateId() {
        String key = String.valueOf(IdGenerator.getId());
        try {
            if (redisUtils.tryLock(key, 10, 15)) {
                int i1 = count - redisUtils.lSize(IdRedisConstant.SNOWFLAKE_ID).intValue();
                List<Object> list = new ArrayList<>();
                for (int i = 0; i < i1; i++) {
                    list.add(sequence.nextId());
                }
                redisUtils.lSet(IdRedisConstant.SNOWFLAKE_ID, list);
            }
        } finally {
            redisUtils.unlock(key);
        }
        return redisUtils.lSize(IdRedisConstant.SNOWFLAKE_ID).intValue();
    }
}